package cn.z2huo.demo.hello.configuration;

import cn.z2huo.demo.hello.cache.api.CacheMetaInfoFactory;
import cn.z2huo.demo.hello.cache.api.CacheService;
import cn.z2huo.demo.hello.cache.impl.CacheMetaInfoFactoryImpl;
import cn.z2huo.demo.hello.cache.impl.SpringCacheKeyGenerator;
import cn.z2huo.demo.hello.cache.impl.SpringCacheManager;
import cn.z2huo.demo.hello.cache.models.RedisModeEnum;
import cn.z2huo.demo.hello.cache.provider.RedisCommanderProvider;
import cn.z2huo.demo.hello.cache.support.redis.RedisCommander;
import cn.z2huo.demo.hello.properties.CacheProperties;
import cn.z2huo.demo.hello.properties.DefaultRedisProperties;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPoolConfig;

/**
 * <p>
 *
 * @author z2huo
 */
@Configuration
//@AutoConfigureAfter({HelloCommon.class, HelloData.class})
@EnableConfigurationProperties({CacheProperties.class, DefaultRedisProperties.class})
@RequiredArgsConstructor
public class HelloCache {

    private final CacheProperties cacheProperties;

    private final DefaultRedisProperties defaultRedisProperties;

    @Value("${hello.web.session.timeout:${web.session.timeout:1800000}}")
    private Long SessionTimeout;


    /**
     * 缓存管理器
     * @param cacheService
     * @param cacheMetaInfoFactory
     * @param applicationContext
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public CacheManager springCacheManager(CacheService cacheService, CacheMetaInfoFactory cacheMetaInfoFactory, ApplicationContext applicationContext) {
        return new SpringCacheManager(cacheService, cacheMetaInfoFactory, applicationContext, cacheProperties.getSpringCacheTimeout());
    }

    /**
     * 缓存键生成器
     * @return
     */
    @Bean
    public KeyGenerator springCacheKeyGenerator() {
        return new SpringCacheKeyGenerator();
    }

    /**
     * 为不同的数据类型生成缓存信息
     * @return
     */
    @Bean
    public CacheMetaInfoFactory cacheMetaInfoFactory() {
        return new CacheMetaInfoFactoryImpl();
    }

    @Bean
    public FactoryBean<RedisCommander> defaultCacheSource() {
        RedisCommanderProvider redisCommonderProvider = new RedisCommanderProvider();
        redisCommonderProvider.setPoolConfig(redisDefaultPoolConfig());
        redisCommonderProvider.setTimeout(defaultRedisProperties.getTimeout());
        redisCommonderProvider.setAddresses(defaultRedisProperties.getAddresses());
        redisCommonderProvider.setPassword(StringUtils.defaultIfEmpty(defaultRedisProperties.getPassword(), null));
        redisCommonderProvider.setSentinelPassword(StringUtils.defaultIfEmpty(defaultRedisProperties.getSentinelPassword(), null));
        redisCommonderProvider.setRedisMode(RedisModeEnum.valueOf(defaultRedisProperties.getMode()));
        redisCommonderProvider.setMaxRedirections(defaultRedisProperties.getMaxRedirections());
        return redisCommonderProvider;
    }

    @Bean
    public JedisPoolConfig redisDefaultPoolConfig() {

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(defaultRedisProperties.getMaxActive());
        jedisPoolConfig.setMaxIdle(defaultRedisProperties.getMaxIdle());
        jedisPoolConfig.setMaxWaitMillis(defaultRedisProperties.getMaxWait());
        jedisPoolConfig.setTestOnBorrow(defaultRedisProperties.isTestOnBorrow());
        return jedisPoolConfig;
    }

}
